package org.ym.database.hibernate.query;

import com.google.gson.JsonObject;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.ym.tools.GsonTool;

import javax.persistence.criteria.*;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.*;

/**
 * @author ym
 */
public class QueryFilter implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 每页默认条数
     */
    public static final int DEFAULT_PAGE_SIZE = 20;
    /**
     * 当前页码
     */
    public static final int DEFAULT_CURRENT_PAGE_INDEX = 0;
    /**
     * 查询条件之间关系
     */
    private FilterRelationEnum filterRelation = FilterRelationEnum.AND;
    /**
     * query之间的关系
     */
    private QueryRelationEnum queryRelationEnum = QueryRelationEnum.AND;
    /**
     * 自身查询存储
     */
    private final FilterCollector selfFilter = new FilterCollector();
    /**
     * 关联表查询存储
     */
    private final HashMap<JoinKey, FilterCollector> selfJoinFilter = new HashMap<>();
    /**
     * 查询字段配置，如count，max，min等
     */
    private final FilterCollector selfSelectFilter = new FilterCollector();
    /**
     * 关联查询字段配置，如count，max，min等
     */
    private final HashMap<JoinKey, FilterCollector> selfSelectJoinFilter = new HashMap<>();
    /**
     * group字段
     */
    private final FilterCollector selfGroupFilter = new FilterCollector();
    /**
     * group字段
     */
    private final HashMap<JoinKey, FilterCollector> selfGroupJoinFilter = new HashMap<>();
    /**
     * having条件
     */
    private final FilterCollector selfHavingFilter = new FilterCollector();
    /**
     * having条件
     */
    private final HashMap<JoinKey, FilterCollector> selfHavingJoinFilter = new HashMap<>();
    /**
     * having条件之间关系
     */
    private FilterRelationEnum havingFilterRelationEnum = FilterRelationEnum.AND;
    /**
     * 存储所有的待查询字段,仅供groupby，max、min等执行后,数组转换使用。
     */
    private final List<String> allExpression = new ArrayList<>();
    /**
     * 分页设置
     */
    private Pageable pageable;
    /**
     * 非分页排序
     */
    private Sort sort;
    /**
     * 子QueryFilter存储位置
     */
    private final List<QueryFilter> childQueryFilter = new ArrayList<>();

    public QueryFilter() {

    }

    /**
     * 添加子QueryFilter,子查询相对父节点，只有查询条件有效
     *
     * @param queryFilter 查询
     * @return 当前对像
     */
    public QueryFilter addChildQueryFilter(QueryFilter queryFilter) {
        if (queryFilter != null && queryFilter != this) {
            //防止添加自己造成死循环
            childQueryFilter.add(queryFilter);
        }
        return this;
    }

    /**
     * 改变自身filter之间的关系
     *
     * @param filterRelation 关系
     * @return 当前对象
     */
    public QueryFilter changeFilterRelation(FilterRelationEnum filterRelation) {
        this.filterRelation = filterRelation;
        return this;
    }

    /**
     * 改变自身having的filter之间的关系
     *
     * @param filterRelation 关系
     * @return 当前对象
     */
    public QueryFilter changeHavingFilterRelation(FilterRelationEnum filterRelation) {
        this.havingFilterRelationEnum = filterRelation;
        return this;
    }

    /**
     * 改变自身与子QueryFilter之间的关系
     *
     * @param queryRelationEnum 关系
     * @return 当前对象
     */
    public QueryFilter changeQueryRelation(QueryRelationEnum queryRelationEnum) {
        this.queryRelationEnum = queryRelationEnum;
        return this;
    }

    /**
     * 添加查询条件
     *
     * @param field              字段名
     * @param value              值
     * @param queryOperateSymbol 操作
     * @return 返回当前对象
     */
    public QueryFilter addFilter(QueryOperateSymbolEnum queryOperateSymbol, String field, String value) {
        selfFilter.addFilter(queryOperateSymbol, field, value);
        return this;
    }

    /**
     * 添加查询条件
     *
     * @param field              字段名
     * @param value              值
     * @param queryOperateSymbol 操作
     * @return 返回当前对象
     */
    public QueryFilter addFilter(QueryOperateSymbolEnum queryOperateSymbol, String field, Number value) {
        selfFilter.addFilter(queryOperateSymbol, field, value);
        return this;
    }


    /**
     * 添加查询条件
     *
     * @param field              字段名
     * @param value              值
     * @param queryOperateSymbol 操作
     * @return 返回当前对象
     */
    public QueryFilter addFilter(QueryOperateSymbolEnum queryOperateSymbol, String field, Date value) {
        selfFilter.addFilter(queryOperateSymbol, field, value);
        return this;
    }

    /**
     * 添加查询条件
     *
     * @param field              字段名
     * @param value              值
     * @param queryOperateSymbol 操作
     * @return 返回当前对象
     */
    public QueryFilter addFilter(QueryOperateSymbolEnum queryOperateSymbol, String field, boolean value) {
        selfFilter.addFilter(queryOperateSymbol, field, value);
        return this;
    }

    /**
     * between条件
     *
     * @param field 字段
     * @param start 起始
     * @param end   结束
     * @return 当前对象
     */
    public QueryFilter between(String field, Date start, Date end) {
        selfFilter.between(field, start, end);
        return this;
    }

    /**
     * between条件
     *
     * @param field 字段
     * @param start 起始
     * @param end   结束
     * @return 当前对象
     */
    public QueryFilter between(String field, Number start, Number end) {
        selfFilter.between(field, start, end);
        return this;
    }

    /**
     * 判断字段是否为空
     *
     * @param field 字段
     * @return 当前对象
     */
    public QueryFilter isNull(String field) {
        selfFilter.isNull(field);
        return this;
    }

    /**
     * 判断字段是否为空
     *
     * @param field 字段
     * @return 当前对象
     */
    public QueryFilter isNotNull(String field) {
        selfFilter.isNotNull(field);
        return this;
    }

    /**
     * in查询
     *
     * @param field 字段
     * @param array 数组
     * @return 当前对象
     */
    public <T> QueryFilter in(String field, T[] array) {
        selfFilter.in(field, array);
        return this;
    }

    /**
     * notIn查询
     *
     * @param field 字段
     * @param array 数组
     * @return 当前对象
     */
    public <T> QueryFilter notIn(String field, T[] array) {
        selfFilter.notIn(field, array);
        return this;
    }

    /**
     * in查询
     *
     * @param field 字段
     * @param list  集合
     * @return 当前对象
     */
    public <T> QueryFilter in(String field, List<T> list) {
        selfFilter.in(field, list);
        return this;
    }

    /**
     * notIn查询
     *
     * @param field 字段
     * @param list  集合
     * @return 当前对象
     */
    public <T> QueryFilter notIn(String field, List<T> list) {
        selfFilter.notIn(field, list);
        return this;
    }

    /**
     * max
     *
     * @param field 字段
     * @return 当前对象
     */
    public QueryFilter max(String field) {
        selfSelectFilter.max(field);
        return this;
    }

    /**
     * min
     *
     * @param field 字段
     * @return 当前对象
     */
    public QueryFilter min(String field) {
        selfSelectFilter.min(field);
        return this;
    }

    /**
     * sum
     *
     * @param field 字段
     * @return 当前对象
     */
    public QueryFilter sum(String field) {
        selfSelectFilter.sum(field);
        return this;
    }

    /**
     * average
     *
     * @param field 字段
     * @return 当前对象
     */
    public QueryFilter average(String field) {
        selfSelectFilter.average(field);
        return this;
    }

    /**
     * count
     *
     * @param field 字段
     * @return 当前对象
     */
    public QueryFilter count(String field) {
        selfSelectFilter.count(field);
        return this;
    }

    /**
     * 添加join表查询条件
     *
     * @param joinKey            join表的key
     * @param field              字段名
     * @param value              值
     * @param queryOperateSymbol 操作
     * @return 返回当前对象
     */
    public QueryFilter addFilter(QueryOperateSymbolEnum queryOperateSymbol, JoinKey joinKey, String field, String value) {
        if (joinKey != null) {
            selfJoinFilter.putIfAbsent(joinKey, new FilterCollector()).addFilter(queryOperateSymbol, field, value);
        }
        return this;
    }

    /**
     * 添加join表查询条件
     *
     * @param joinKey            join表的key
     * @param field              字段名
     * @param value              值
     * @param queryOperateSymbol 操作
     * @return 返回当前对象
     */
    public QueryFilter addFilter(QueryOperateSymbolEnum queryOperateSymbol, JoinKey joinKey, String field, Number value) {
        if (joinKey != null) {
            selfJoinFilter.putIfAbsent(joinKey, new FilterCollector()).addFilter(queryOperateSymbol, field, value);
        }
        return this;
    }


    /**
     * 添加join表查询条件
     *
     * @param joinKey            join表的key
     * @param field              字段名
     * @param value              值
     * @param queryOperateSymbol 操作
     * @return 返回当前对象
     */
    public QueryFilter addFilter(QueryOperateSymbolEnum queryOperateSymbol, JoinKey joinKey, String field, Date value) {
        if (joinKey != null) {
            selfJoinFilter.putIfAbsent(joinKey, new FilterCollector()).addFilter(queryOperateSymbol, field, value);
        }
        return this;
    }

    /**
     * 添加join表查询条件
     *
     * @param joinKey            join表的key
     * @param field              字段名
     * @param value              值
     * @param queryOperateSymbol 操作
     * @return 返回当前对象
     */
    public QueryFilter addFilter(QueryOperateSymbolEnum queryOperateSymbol, JoinKey joinKey, String field, boolean value) {
        if (joinKey != null) {
            selfJoinFilter.putIfAbsent(joinKey, new FilterCollector()).addFilter(queryOperateSymbol, field, value);
        }
        return this;
    }

    /**
     * join表between条件
     *
     * @param joinKey join表的key
     * @param field   字段
     * @param start   起始
     * @param end     结束
     * @return 当前对象
     */
    public QueryFilter between(JoinKey joinKey, String field, Date start, Date end) {
        if (joinKey != null) {
            selfJoinFilter.putIfAbsent(joinKey, new FilterCollector()).between(field, start, end);
        }
        return this;
    }

    /**
     * join表between条件
     *
     * @param joinKey join表的key
     * @param field   字段
     * @param start   起始
     * @param end     结束
     * @return 当前对象
     */
    public QueryFilter between(JoinKey joinKey, String field, Number start, Number end) {
        if (joinKey != null) {
            selfJoinFilter.putIfAbsent(joinKey, new FilterCollector()).between(field, start, end);
        }
        return this;
    }

    /**
     * 判断join表字段是否为空
     *
     * @param joinKey join表的key
     * @param field   字段
     * @return 当前对象
     */
    public QueryFilter isNull(JoinKey joinKey, String field) {
        if (joinKey != null) {
            selfJoinFilter.putIfAbsent(joinKey, new FilterCollector()).isNull(field);
        }
        return this;
    }

    /**
     * 判断join表字段是否为空
     *
     * @param joinKey join表的key
     * @param field   字段
     * @return 当前对象
     */
    public QueryFilter isNotNull(JoinKey joinKey, String field) {
        if (joinKey != null) {
            selfJoinFilter.putIfAbsent(joinKey, new FilterCollector()).isNotNull(field);
        }
        return this;
    }

    /**
     * join表in查询
     *
     * @param field   字段
     * @param joinKey join表的key
     * @param array   数组
     * @return 当前对象
     */
    public <T> QueryFilter in(JoinKey joinKey, String field, T[] array) {
        if (joinKey != null) {
            selfJoinFilter.putIfAbsent(joinKey, new FilterCollector()).in(field, array);
        }
        return this;
    }

    /**
     * join表notIn查询
     *
     * @param field   字段
     * @param joinKey join表的key
     * @param array   数组
     * @return 当前对象
     */
    public <T> QueryFilter notIn(JoinKey joinKey, String field, T[] array) {
        if (joinKey != null) {
            selfJoinFilter.putIfAbsent(joinKey, new FilterCollector()).notIn(field, array);
        }
        return this;
    }

    /**
     * join表in查询
     *
     * @param field   字段
     * @param joinKey join表的key
     * @param list    集合
     * @return 当前对象
     */
    public <T> QueryFilter in(JoinKey joinKey, String field, List<T> list) {
        if (joinKey != null) {
            selfJoinFilter.putIfAbsent(joinKey, new FilterCollector()).in(field, list);
        }
        return this;
    }

    /**
     * join表notIn查询
     *
     * @param field   字段
     * @param joinKey join表的key
     * @param list    集合
     * @return 当前对象
     */
    public <T> QueryFilter notIn(JoinKey joinKey, String field, List<T> list) {
        if (joinKey != null) {
            selfJoinFilter.putIfAbsent(joinKey, new FilterCollector()).notIn(field, list);
        }
        return this;
    }

    /**
     * join表max
     *
     * @param field   字段
     * @param joinKey join表的key
     * @return 当前对象
     */
    public QueryFilter max(JoinKey joinKey, String field) {
        if (joinKey != null) {
            selfSelectJoinFilter.putIfAbsent(joinKey, new FilterCollector()).max(field);
        }
        return this;
    }

    /**
     * join表min
     *
     * @param field   字段
     * @param joinKey join表的key
     * @return 当前对象
     */
    public QueryFilter min(JoinKey joinKey, String field) {
        if (joinKey != null) {
            selfSelectJoinFilter.putIfAbsent(joinKey, new FilterCollector()).min(field);
        }
        return this;
    }

    /**
     * join表sum
     *
     * @param field   字段
     * @param joinKey join表的key
     * @return 当前对象
     */
    public QueryFilter sum(JoinKey joinKey, String field) {
        if (joinKey != null) {
            selfSelectJoinFilter.putIfAbsent(joinKey, new FilterCollector()).sum(field);
        }
        return this;
    }

    /**
     * join表average
     *
     * @param field   字段
     * @param joinKey join表的key
     * @return 当前对象
     */
    public QueryFilter average(JoinKey joinKey, String field) {
        if (joinKey != null) {
            selfSelectJoinFilter.putIfAbsent(joinKey, new FilterCollector()).average(field);
        }
        return this;
    }

    /**
     * join表count
     *
     * @param field   字段
     * @param joinKey join表的key
     * @return 当前对象
     */
    public QueryFilter count(JoinKey joinKey, String field) {
        if (joinKey != null) {
            selfSelectJoinFilter.putIfAbsent(joinKey, new FilterCollector()).count(field);
        }
        return this;
    }

    /**
     * 添加查询字段
     *
     * @param field 字段名
     * @return 数据
     */
    public QueryFilter addField(String field) {
        selfSelectFilter.addFiled(field);
        return this;
    }

    /**
     * 添加查询字段
     *
     * @param field 字段名
     * @return 数据
     */
    public QueryFilter addJoinField(JoinKey joinKey, String field) {
        if (joinKey != null) {
            selfSelectJoinFilter.putIfAbsent(joinKey, new FilterCollector()).addFiled(field);
        }
        return this;
    }

    /**
     * 分组
     *
     * @param field 分组字段
     * @return 当前对象
     */
    public QueryFilter groupBy(String field) {
        addField(field);
        selfGroupFilter.group(field);
        return this;
    }

    /**
     * 分组
     *
     * @param joinKey 关联表字段
     * @param field   分组字段
     * @return 当前对象
     */
    public QueryFilter groupBy(JoinKey joinKey, String field) {
        if (joinKey != null) {
            addJoinField(joinKey, field);
            selfGroupJoinFilter.putIfAbsent(joinKey, new FilterCollector()).group(field);
        }
        return this;
    }

    /**
     * having查询条件
     *
     * @param queryOperateSymbol 支持count、min、max、sum、avg等
     * @param field              字段
     * @param value              值
     * @return 当前对象
     */
    public QueryFilter having(QueryOperateSymbolEnum queryOperateSymbol, String field, Number value) {
        selfHavingFilter.addFilter(queryOperateSymbol, field, value);
        return this;
    }

    /**
     * having查询条件
     *
     * @param queryOperateSymbol 支持count、min、max、sum、avg等
     * @param joinKey            关联字段表
     * @param field              字段
     * @param value              值
     * @return 当前对象
     */
    public QueryFilter having(QueryOperateSymbolEnum queryOperateSymbol, JoinKey joinKey, String field, Number value) {
        if (joinKey != null) {
            selfHavingJoinFilter.putIfAbsent(joinKey, new FilterCollector()).addFilter(queryOperateSymbol, field, value);
        }
        return this;
    }

    /**
     * 设置排序
     *
     * @param direction  排序方向
     * @param properties 排序字段
     * @return 当前对象
     */
    public QueryFilter setSortOrder(Sort.Direction direction, String... properties) {
        if (direction != null && properties != null && properties.length > 0) {
            setSortOrder(Sort.by(direction, properties));
        }
        return this;
    }

    /**
     * 设置排序，默认第0页，每页20条
     *
     * @param sort 排序
     * @return 当前对象
     */
    public QueryFilter setSortOrder(Sort sort) {
        if (sort != null) {
            if (pageable != null) {
                pageable = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
            } else {
                this.sort = sort;
            }
        }
        return this;
    }

    /**
     * 设置分页条件
     *
     * @param pageable PageRequest对象
     * @return 当前对象
     */
    public QueryFilter setPageable(Pageable pageable) {
        if (pageable != null) {
            this.pageable = pageable;
        }
        return this;
    }

    /**
     * 设置当前页码，默认每页20条数据
     *
     * @param currentPageIndex 当前页码
     * @return 当前对象
     */
    public QueryFilter setCurrentPageIndex(int currentPageIndex) {
        if (pageable != null) {
            pageable = pageable.withPage(currentPageIndex);
        } else {
            if (sort == null) {
                pageable = PageRequest.of(currentPageIndex, DEFAULT_PAGE_SIZE);
            } else {
                pageable = PageRequest.of(currentPageIndex, DEFAULT_PAGE_SIZE, sort);
            }
        }
        return this;
    }

    /**
     * 设置分页大小
     *
     * @param pageSize 每页大小
     * @return 当前对象
     */
    public QueryFilter setPageSize(int pageSize) {
        if (pageable != null) {
            pageable = PageRequest.of(pageable.getPageNumber(), pageSize, pageable.getSort());
        } else {
            if (sort == null) {
                pageable = PageRequest.of(DEFAULT_CURRENT_PAGE_INDEX, pageSize);
            } else {
                pageable = PageRequest.of(DEFAULT_CURRENT_PAGE_INDEX, pageSize, sort);
            }
        }
        return this;
    }

    /**
     * 设置分页大小和当前页
     *
     * @param pageSize         页大小
     * @param currentPageIndex 页码,从0开始
     * @return 当前对象
     */
    public QueryFilter setPageSizeAndCurrentIndex(int currentPageIndex, int pageSize) {
        if (pageable != null) {
            pageable = PageRequest.of(currentPageIndex, pageSize, pageable.getSort());
        } else {
            if (sort == null) {
                pageable = PageRequest.of(currentPageIndex, pageSize);
            } else {
                pageable = PageRequest.of(currentPageIndex, pageSize, sort);
            }
        }
        return this;
    }

    /**
     * 转换为Specification
     *
     * @param classZ 当前model的类
     * @param <T>    任意类型
     * @return specification
     */
    public <T> Specification<T> toSpecification(Class<T> classZ) {
        return new Specification<T>() {
            @Override
            public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                HashMap<JoinKey, Join> joinTableMap = new HashMap<>();
                //处理查询字段
                dealSelectExpression(root, query, criteriaBuilder, joinTableMap);
                //分组字段处理
                dealGroupExpression(root, query, criteriaBuilder, joinTableMap);
                //构造查询条件
                return QueryFilter.this.toPredicate(root, criteriaBuilder, joinTableMap);
            }
        };
    }

    /**
     * 处理分组条件
     *
     * @param root            主表
     * @param query           查询
     * @param criteriaBuilder 查询
     * @param joinTableMap    链接表
     */
    private void dealGroupExpression(Root root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder, HashMap<JoinKey, Join> joinTableMap) {
        List<Expression> groupExpressionList = new ArrayList<>(selfGroupFilter.generateExpression(root, criteriaBuilder));
        if (!selfGroupJoinFilter.isEmpty()) {
            Iterator<Map.Entry<JoinKey, FilterCollector>> iterator = selfGroupJoinFilter.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<JoinKey, FilterCollector> entry = iterator.next();
                if (entry.getKey().isEffective()) {
                    if (!joinTableMap.containsKey(entry.getKey())) {
                        joinTableMap.put(entry.getKey(), root.join(entry.getKey().getKey(), entry.getKey().getJoinType()));
                    }
                    groupExpressionList.addAll(entry.getValue().generateExpression(joinTableMap.get(entry.getKey()), criteriaBuilder));
                }
            }
        }
        if (!groupExpressionList.isEmpty()) {
            query.groupBy(groupExpressionList.toArray(new Expression[0]));
            //处理having函数
            dealHaving(root,query,criteriaBuilder,joinTableMap);
        }
    }

    /**
     * having条件处理
     * @param root 主表
     * @param query 查询
     * @param criteriaBuilder 查询
     * @param joinTableMap 关联表
     */
    private void dealHaving(Root root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder, HashMap<JoinKey, Join> joinTableMap) {
        List<Predicate> fullPredicateList = new ArrayList<>(selfHavingFilter.generatePredicate(root, criteriaBuilder));
        if (!selfHavingJoinFilter.isEmpty()) {
            Iterator<Map.Entry<JoinKey, FilterCollector>> iterator = selfHavingJoinFilter.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<JoinKey, FilterCollector> entry = iterator.next();
                if (entry.getKey().isEffective()) {
                    if (!joinTableMap.containsKey(entry.getKey())) {
                        joinTableMap.put(entry.getKey(), root.join(entry.getKey().getKey(), entry.getKey().getJoinType()));
                    }
                    fullPredicateList.addAll(entry.getValue().generatePredicate(joinTableMap.get(entry.getKey()), criteriaBuilder));
                }
            }
        }
        if(!fullPredicateList.isEmpty()) {
            if (havingFilterRelationEnum == FilterRelationEnum.AND) {
                query.having(criteriaBuilder.and(fullPredicateList.toArray(new Predicate[0])));
            } else {
                query.having(criteriaBuilder.or(fullPredicateList.toArray(new Predicate[0])));
            }
        }
    }

    /**
     * 处理要查询的字段
     *
     * @param root            主表
     * @param query           查询
     * @param criteriaBuilder 查询
     * @param joinTableMap    链接表
     */
    private void dealSelectExpression(Root root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder, HashMap<JoinKey, Join> joinTableMap) {
        allExpression.clear();
        allExpression.addAll(selfSelectFilter.toDisplayKey());
        List<Expression> fullExpressionList = new ArrayList<>(selfSelectFilter.generateExpression(root, criteriaBuilder));
        //先处理特殊查询字段
        if (!selfSelectJoinFilter.isEmpty()) {
            Iterator<Map.Entry<JoinKey, FilterCollector>> iterator = selfSelectJoinFilter.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<JoinKey, FilterCollector> entry = iterator.next();
                if (entry.getKey().isEffective()) {
                    if (!joinTableMap.containsKey(entry.getKey())) {
                        joinTableMap.put(entry.getKey(), root.join(entry.getKey().getKey(), entry.getKey().getJoinType()));
                    }
                    allExpression.addAll(entry.getValue().toDisplayKey(entry.getKey()));
                    fullExpressionList.addAll(entry.getValue().generateExpression(joinTableMap.get(entry.getKey()), criteriaBuilder));
                }
            }
        }
        if (!fullExpressionList.isEmpty()) {
            query.multiselect(fullExpressionList.toArray(new Expression[0]));
        } else {
            query.multiselect(root);
        }
    }

    /**
     * 当前query转换为predicate ，不包含子queryfilter转换
     *
     * @param root            root
     * @param criteriaBuilder criteriaBuilder
     * @param joinTableMap    join表map
     * @return predicate
     */
    private Predicate toPredicate(Root root, CriteriaBuilder criteriaBuilder, HashMap<JoinKey, Join> joinTableMap) {
        Predicate predicate;
        List<Predicate> fullPredicateList = new ArrayList<>(selfFilter.generatePredicate(root, criteriaBuilder));
        if (!selfJoinFilter.isEmpty()) {
            Iterator<Map.Entry<JoinKey, FilterCollector>> iterator = selfJoinFilter.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<JoinKey, FilterCollector> entry = iterator.next();
                if (entry.getKey().isEffective()) {
                    if (!joinTableMap.containsKey(entry.getKey())) {
                        joinTableMap.put(entry.getKey(), root.join(entry.getKey().getKey(), entry.getKey().getJoinType()));
                    }
                    fullPredicateList.addAll(entry.getValue().generatePredicate(joinTableMap.get(entry.getKey()), criteriaBuilder));
                }
            }
        }
        if (filterRelation == FilterRelationEnum.AND) {
            predicate = criteriaBuilder.and(fullPredicateList.toArray(new Predicate[0]));
        } else {
            predicate = criteriaBuilder.or(fullPredicateList.toArray(new Predicate[0]));
        }
        if (!childQueryFilter.isEmpty()) {
            //子查询处理
            fullPredicateList.clear();
            fullPredicateList.add(predicate);
            for (QueryFilter queryFilter : childQueryFilter) {
                fullPredicateList.add(queryFilter.toPredicate(root, criteriaBuilder, joinTableMap));
            }
            if (queryRelationEnum == QueryRelationEnum.AND) {
                predicate = criteriaBuilder.and(fullPredicateList.toArray(new Predicate[0]));
            } else {
                predicate = criteriaBuilder.or(fullPredicateList.toArray(new Predicate[0]));
            }
        }
        return predicate;
    }

    /**
     * 是否分页
     *
     * @return true：分页 false：不分页
     */
    public boolean isPaging() {
        return pageable != null;
    }

    /**
     * 获取分页信息
     *
     * @return
     */
    public Pageable getPageable() {
        return pageable;
    }

    /**
     * 获取排序信息
     *
     * @return
     */
    public Sort getSort() {
        if (pageable != null) {
            return pageable.getSort();
        }
        return sort;
    }

    /**
     * 清空条件与分页条件
     *
     * @return 当前对象
     */
    public QueryFilter clear() {
        pageable = null;
        sort = null;
        selfFilter.clear();
        selfSelectFilter.clear();
        selfJoinFilter.clear();
        selfSelectJoinFilter.clear();
        selfGroupFilter.clear();
        selfGroupJoinFilter.clear();
        childQueryFilter.clear();
        selfHavingFilter.clear();
        selfHavingJoinFilter.clear();
        filterRelation = FilterRelationEnum.AND;
        queryRelationEnum = QueryRelationEnum.AND;
        allExpression.clear();
        return this;
    }

    /**
     * 转换数组集合结果集为JsonObject集合结果集
     * @param objectList 数组集合结果集
     * @return JsonObject集合结果集
     */
    public List<JsonObject> changeToJsonObject(List objectList){
        List<JsonObject> list = new ArrayList<>();
        if(!objectList.isEmpty()){
            if(!allExpression.isEmpty()){
                for(Object o : objectList){
                    list.add(GsonTool.getGson().fromJson(GsonTool.getGson().toJson(changeArrayToMap(o)),JsonObject.class));
                }
            }else{
                list = GsonTool.getGson().fromJson(GsonTool.getGson().toJson(objectList),GsonTool.toListType(JsonObject.class));
            }

        }
        return list;
    }

    /**
     * 转换数组为hashmap
     * @param o 数组
     * @return 对象
     */
    private Map<String,Object> changeArrayToMap(Object o){
        int length = Array.getLength(o);
        HashMap<String, Object> map = new HashMap<>(length / 3 * 4);
        if(length == allExpression.size()) {
            for (int i = 0; i < length; i++) {
                map.put(allExpression.get(i),Array.get(o,i));
            }
        }
        return map;
    }


    @Override
    public String toString(){
        return GsonTool.getGson().toJson(this);
    }
}
